﻿using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using Microsoft.ApplicationInsights.AspNetCore.Extensions;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using ZilLion.Service.Core.Log;
using ZilLion.Service.ZilLionOss.Domain.Repositorys.Interface;
using ContentDispositionHeaderValue = System.Net.Http.Headers.ContentDispositionHeaderValue;
using MediaTypeHeaderValue = System.Net.Http.Headers.MediaTypeHeaderValue;

namespace ZilLion.Service.ZilLionOss.Controllers
{
    /// <summary>
    ///     Oss 代理
    /// </summary>
    public class OssGatewayProxyController : OssControllerBase
    {
        private readonly IOssCompanyMoudleReponsitory _ossCompanyMoudleReponsitory;

        /// <summary>
        ///     构造函数
        /// </summary>
        /// <param name="ossCompanyMoudleReponsitory"></param>
        public OssGatewayProxyController(IOssCompanyMoudleReponsitory ossCompanyMoudleReponsitory)
        {
            _ossCompanyMoudleReponsitory = ossCompanyMoudleReponsitory;
        }

        private byte[] StreamToBytes(Stream stream)
        {
            var bytes = new byte[stream.Length];
            stream.Read(bytes, 0, bytes.Length);
            // 设置当前流的位置为流的开始
            stream.Seek(0, SeekOrigin.Begin);
            return bytes;
        }

        /// <summary>
        ///     post 转发代理
        /// </summary>
        /// <returns></returns>
        private string HttpPostProxyRedirect(string realurl, HttpContext context)
        {
            using (var http = new HttpClient())
            {
                http.Timeout = new TimeSpan(0, 0, 120);
                var contenttype = context.Request.Headers[HeaderNames.ContentType].ToString();
                if (contenttype.ToLower().Contains("multipart/form-data"))
                {
                    var files = Request.Form.Files;
                    using (var content = new MultipartFormDataContent())
                    {
                        foreach (var file in files)
                        {
                            if (file == null) continue;
                            var filename = ContentDispositionHeaderValue
                                .Parse(file.ContentDisposition)
                                .FileName
                                .Trim('"');
                            var filestream = file.OpenReadStream();
                            var fileContent = new ByteArrayContent(StreamToBytes(filestream));
                            content.Add(fileContent, filename, filename);
                        }
                        var response = http.PostAsync(realurl, content).Result;
                        return response.Content.ReadAsStringAsync().Result;
                    }
                }
                using (var reader = new StreamReader(context.Request.Body))
                {
                    var stringContent = new StringContent(reader.ReadLineAsync().Result);
                    stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                    var realResult = http.PostAsync(realurl, stringContent).Result;
                    return realResult.Content.ReadAsStringAsync().Result;
                }
            }
        }

        /// <summary>
        ///     put转发代理
        /// </summary>
        /// <returns></returns>
        private string HttpPutProxyRedirect(string realurl, HttpContext context)
        {
            using (var http = new HttpClient())
            {
                http.Timeout = new TimeSpan(0, 0, 120);
                using (var reader = new StreamReader(context.Request.Body))
                {
                    var stringContent = new StringContent(reader.ReadLineAsync().Result);
                    stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                    var realResult = http.PutAsync(realurl, stringContent).Result;
                    return realResult.Content.ReadAsStringAsync().Result;
                }
            }
        }

        /// <summary>
        ///     put转发代理
        /// </summary>
        /// <returns></returns>
        private string HttpDeleteProxyRedirect(string realurl, HttpContext context)
        {
            using (var http = new HttpClient())
            {
                http.Timeout = new TimeSpan(0, 0, 120);
                var realResult = http.DeleteAsync(realurl).Result;
                return realResult.Content.ReadAsStringAsync().Result;
            }
        }

        /// <summary>
        ///     代理Action
        /// </summary>
        /// <param name="modulekey"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpGet]
        [HttpDelete]
        [HttpPost]
        [HttpPut]
        [HttpOptions]
        public IActionResult RedirectToRealApi([FromRoute] string modulekey, string token = null)
        {
            var company = GetZlCompanyKey();
            var realurl = GetRealUrl(HttpContext.Request.GetUri(), company, modulekey);
            if (HttpContext.Request.Method.ToLower() == "get")
                return Redirect(realurl);
            if (HttpContext.Request.Method.ToLower() == "post")
                return Content(HttpPostProxyRedirect(realurl, HttpContext), "application/json;charset=utf-8");
            if (HttpContext.Request.Method.ToLower() == "put")
                return Content(HttpPutProxyRedirect(realurl, HttpContext), "application/json;charset=utf-8");
            if (HttpContext.Request.Method.ToLower() == "delete")
                return Content(HttpDeleteProxyRedirect(realurl, HttpContext), "application/json;charset=utf-8");
            return new NotFoundResult();
        }

        private string GetRealUrl(Uri proxyUri, string companyKey, string modulekey)
        {
            if (modulekey.ToLower() == "ossback" || modulekey.ToLower() == "jwt" || modulekey.ToLower() == "img"
            ) //由于各个公司使用的是一套登录服务,所以是授权服务的话,直接去掉/ossgateway 即可
            {
                var proxyPath = proxyUri.AbsolutePath.ToLower();
                var realPath = proxyPath.Replace("/ossgateway", string.Empty);
                var result = $"{proxyUri.Scheme}://{proxyUri.Authority}{realPath}{proxyUri.Query}";
                return result;
            }
            var moudle = _ossCompanyMoudleReponsitory.GetCompanyMoudleByCompanyKey(companyKey);
            var first = moudle?.FirstOrDefault(x => x.MoudleKey == modulekey);
            if (first == null) throw new Exception("获取代理配置失败");
            {
                var realhost = first.MoudleGateWay;
                if (realhost.EndsWith("/"))
                    realhost = realhost.Left(realhost.Length - 1);
                realhost = $"{realhost}/api/{first.MoudleKey.ToLower()}";
                //"Api/Gateway/{modulekey}/{*path}"
                var proxyPath = proxyUri.AbsolutePath.ToLower();
                var replaceString = $"/api/ossgateway/{modulekey.ToLower()}";
                var realpath = proxyPath.Replace(replaceString, string.Empty);
                var realUrl = $"{realhost}{realpath}{proxyUri.Query}";
                ZilLionLogManager.Instance().Trace(realUrl);
                return realUrl;
            }
        }
    }
}